﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelnetRouterApplication.Connection;

namespace TelnetRouterApplication.Control
{
    public class ConnectionHandler
    {
        private static bool _DEBUG = false;
        public static bool DEBUG
        {
            get { return ConnectionHandler._DEBUG; }
            set { ConnectionHandler._DEBUG = value; }
        }
        private static ConnectionHandler instance;

        private TelnetConnection _telnetConnection;
        public TelnetConnection TelnetConnection
        {
            get { return _telnetConnection; }
            set { _telnetConnection = value; }
        }
        private bool _connected;
        public bool Connected
        {
            get { return _connected; }
            set { _connected = value; }
        }

        private static IpModel connectionIp;

        public static IpModel ConnectionIp
        {
            get { return ConnectionHandler.connectionIp; }
            set { ConnectionHandler.connectionIp = value; }
        }

        private static string password;

        public static string Password
        {
            get { return ConnectionHandler.password; }
            set { ConnectionHandler.password = value; }
        }

        private ConnectionHandler() { }

        public static ConnectionHandler GetInstance()
        {
            if (instance == null)
            {
                instance = new ConnectionHandler();
            }
            return instance;
        }

        public void Desconnect()
        {
            TelnetConnection.Desconnect();
        }

        public bool Connect()
        {
            if (ConnectionIp != null)
            {
                return Connect(ConnectionIp);
            }
            else
            {
                return false;
            }
        }

        public bool Connect(string ip, int port)
        {
            //Método funciona igual ao connect passando um IpModel, mas assim você não precisa instanciar o objeto ipmodel
            return Connect(new IpModel(ip, port));
        }

        public bool Connect(IpModel ipModel)
        {
            try
            {
                TelnetConnection = new TelnetConnection(ipModel);
                Connected = TelnetConnection.Connect();
            }
            catch (System.Net.Sockets.SocketException e)
            {
                if (DEBUG)
                {
                    System.Diagnostics.Debug.WriteLine("Lançamento de exceção!");
                    System.Diagnostics.Debug.WriteLine(e.Message);
                }
                return false;
            }
            if (Connected)
            {
                ConnectionHandler.ConnectionIp = ipModel;
            }
            return Connected;
        }

        public bool NeedPassword()
        {
            if (Connected)
            {
                List<string> messages = TelnetConnection.ReceiveMessage();
                //Verifica se a última mensagem contém "assword", escrito. 
                //Usamos "assword" para não lidar com a caixa do caractere 'P', ignorando-o
                string lastMessage = messages[messages.Count-1];
                if (lastMessage.Contains("assword"))
                {
                    return true;
                }
            }
            return false;
        }

        /**
         * Retorna verdadeiro caso a senha passada seja correta.
         */
        public bool SendPassword(string password)
        {
            TelnetConnection.SendMessage(password);
            List<string> messages = TelnetConnection.ReceiveMessage();
            //Verifica se a última mensagem recebida não possui "assword", 
            //caso possua, o password estava errado.
            string lastMessage = messages[messages.Count-1];
            if (lastMessage.Contains("assword"))
            {
                return false;
            }
            Password = password;
            return true;
        }

        public void SendMessage(string message)
        {
            //Encapsula o método de enviar mensagem do telnetConnection
            TelnetConnection.SendMessage(message);
        }

        public void SendMessageNoEnter(string message)
        {
            //Encapsula o método de enviar mensagem do telnetConnection
            TelnetConnection.SendMessageNoEnter(message);
        }

        public List<string> ReceiveMessage()
        {
            //Encapsula o método de receber mensagem do telnetConnection
            return TelnetConnection.ReceiveMessage();
        }

        public List<string> ReceiveMessage(bool split)
        {
            //Encapsula o método de receber mensagem do telnetConnection
            return TelnetConnection.ReceiveMessage(split);
        }

        public string ReceiveMessageWithNoSpaces()
        {
            string messageTotal = "";
            bool endReached = false;
            int loopEnder = 0;
            while (!endReached)
            {
                ConnectionHandler.GetInstance().Delay(200);

                //Recebe as mensagens sem dar o split
                List<string> messages = ReceiveMessage(false);

                if (messages.Count > 0)
                {
                    //Procura por um # nas mensagens recebidas para saber se terminaram as mensagens do show run
                    if (Contains(messages, "#") || loopEnder == 10)
                    {
                        if (DEBUG)
                        {
                            System.Diagnostics.Debug.WriteLine("'#' encontrado!");
                        }
                        endReached = true;
                    }
                    else
                    {
                        if (DEBUG)
                        {
                            System.Diagnostics.Debug.WriteLine("Não foi achado '#' nas mensagens.");
                        }
                    }
                    messageTotal += messages[0];
                }
                ConnectionHandler.GetInstance().SendMessageNoEnter(" ");
                loopEnder++;
            }
            ConnectionHandler.GetInstance().SendMessage("");
            return messageTotal;
        }

        private bool Contains(List<string> list, string value)
        {
            //Método para verificar se existe o valor passado na lista de strings
            foreach (string message in list)
            {
                /*
                if(DEBUG)
                {
                    System.Diagnostics.Debug.WriteLine("=>"+message);
                }
                */
                if (message.Equals(value) || message.Contains(value))
                {
                    return true;
                }
            }
            return false;
        }

        public void Delay(int millisseconds)
        {
            TelnetConnection.Delay(millisseconds);
        }
    }
}
